#ifndef _MONITOR_HPP_
#define _MONITOR_HPP_

#include "config.hpp"

#include <vector>
#include <iostream>

template <typename Buffer_t>
class Monitor : private boost::noncopyable
{
private:
    std::vector<Buffer_t> _buffer;

    int _buffer_size;
    int _buffered;

    boost::condition_variable _cond_not_empty;
    boost::condition_variable _cond_empty;

    boost::mutex _monitor;

public:
    Monitor( int buffer_size)
    {
        if ( buffer_size < 1)
        {
                _buffer_size = 1;
        }
        else
        {
            _buffer_size = buffer_size;
        }

        _buffered = 0;
    }
    Monitor()
    {
        _buffer_size = 1;
        _buffered = 0;
    }
    ~Monitor()
    {
        _buffer_size = 0;
    }
//////////////////////////////
    void Send ( Buffer_t &data)
    {
        boost::mutex::scoped_lock  lock( _monitor);

        while ( _buffered == _buffer_size)
            _cond_empty.wait( lock);

        _buffer.push_back( data);
        _buffered++;

        _cond_not_empty.notify_one();
    }
    Buffer_t Receive( bool & success)
    {
        boost::mutex::scoped_lock lock( _monitor);

        while ( _buffered == 0)
        {   
            try
            {
                _cond_not_empty.wait( lock);
            }
            catch( ...)
            {
                std::cout << "ggg" << std::endl;
                success = false;
                Buffer_t _data;
                return _data;
            }
        }
        Buffer_t _data = _buffer.back();
        _buffer.pop_back();

        _buffered--;

        _cond_empty.notify_one();

        success = true;
        return _data;
    }
    Buffer_t Receive()
    {
        boost::mutex::scoped_lock lock( _monitor);

        while ( _buffered == 0)
        {
            _cond_not_empty.wait( lock);
        }
        Buffer_t _data = _buffer.back();
        _buffer.pop_back();

        _buffered--;

        _cond_empty.notify_one();

        return _data;
    }
};

#endif // _MONITOR_HPP_
